//
// Created by Martin on 2023/4/11.
//

#ifndef MUDUO_OSFILE_H
#define MUDUO_OSFILE_H

#include <map>
#include <mutex>

namespace ftp {
namespace filesystem {

/// File status map to share reading file.
typedef enum FileStatusType : int
{
    kFileStatusIdle = 0,  // invalid status
    kFileStatusRead,
    kFileStatusWrite,
} FileStatus_t;

struct OsFileStatus
{
public:
    FileStatus_t status;
    // number of users.
    // < 0: occupied by a writer;
    //  0 : no reader and no writer;
    // > 0: occupied by readers.
    int numUsers;

    OsFileStatus()
            : status(kFileStatusIdle), numUsers(0)
    {}

    explicit OsFileStatus(FileStatus_t fs)
            : status(fs)
            , numUsers(fs == kFileStatusIdle ? 0 : (fs == kFileStatusWrite ? -1 : 1))
    {}
};

/// thread-safe
class OsFile
{
public:
    OsFile(const OsFile& ) = delete;
    OsFile &operator=(const OsFile& ) = delete;
    bool allocFile(const std::string& pathname, FileStatus_t status);
    bool allocFile(const std::string& pathname, const char* status);
    void freeFile(const std::string& pathname);

    static OsFile &getInstance();

private:
    OsFile() = default;
    ~OsFile() = default;

    bool doAllocFile(const std::string& pathname, FileStatus_t status);
    void doFreeFile(const std::string& pathname);

    std::map<std::string, OsFileStatus> files_;
    std::mutex mutex_;
};

#define OSFileInstance OsFile::getInstance()

const char* fileStatusToString(FileStatus_t status);
FileStatus_t toFileStatus(const char* str);

} // namespace filesystem
} // namespace ftp

#endif //MUDUO_OSFILE_H
